package com.example.filter;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;
import java.util.Objects;

/**
 * 客户端请求（前端）
 *     ↓
 * 服务端Tomcat（容器）接收到请求
 *     ↓
 * 进入Filter的doFilter()方法【请求前处理】 ✅ （你说的请求前处理发生在这里）
 *     ↓
 * chain.doFilter(request,response); //继续传递请求
 *     ↓
 * 进入Spring的DispatcherServlet
 *     ↓
 * 找到具体的Controller方法并执行
 *     ↓
 * Controller处理完成，返回响应结果
 *     ↓
 * 回到Filter的doFilter()方法中的后半部分【响应后处理】 ✅（你说的响应后处理发生在这里）
 *     ↓
 * 最终响应返回给客户端（前端）
 */

/**
 * 自定义的过滤器：实现根据IP统计访问次数
 * <p>
 * init()：当服务器启动并创建Filter实例时调用（仅调用一次）。
 * doFilter()：每次请求/响应经过Filter时都会调用。
 * destroy()：销毁时调用，释放资源。
 * <p>
 * init()：当服务器启动并创建Filter实例时调用（仅调用一次）。
 * doFilter()：每次请求/响应经过Filter时都会调用。
 * destroy()：销毁时调用，释放资源。
 */

/**
 * init()：当服务器启动并创建Filter实例时调用（仅调用一次）。
 * doFilter()：每次请求/响应经过Filter时都会调用。
 * destroy()：销毁时调用，释放资源。
 */

/**
 * Spring Boot 默认不会自动识别 @WebFilter 注解
 * 在 Spring Boot 启动类上加上 @ServletComponentScan 注解
 * 此时 @WebFilter 即可生效
 */
@WebFilter(urlPatterns = "/*") // 拦截所有请求
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    /**
     * @WebFilter("/*") 表示拦截所有请求，也可指定特定路径，如 /user/*。
     * FilterChain表示过滤器链，通过chain.doFilter(request, response)继续向下执行。
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 访问的ip
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String ip = request.getRemoteAddr();
        // 统计访问次数并输出
        HttpSession session = request.getSession();
        Integer count = (Integer) session.getAttribute("count");
        count = Objects.isNull(count) ? 1 : ++count;
        System.out.println("ip: " + ip + " count: " + count);
        session.setAttribute("count", count);
        // 放行
        /**
         * // 请求前处理
         * chain.doFilter(req, resp); // 继续传递请求
         * // 响应后处理
         */
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

}
/**
 * Filter处理请求和响应的注意事项
 * 请求和响应对象的生命周期：
 * 请求体数据只能读取一次，需包装后才能重复使用。
 * 响应数据写入完成后再去修改需要使用HttpServletResponseWrapper进行包装。
 * 执行效率：
 * Filter中应避免耗时过长的操作，以免降低整体请求处理性能。
 * 执行顺序：
 * Filter执行顺序可通过FilterRegistrationBean的order属性控制。
 */